/*    Copyright 2010 Tobias Marschall
 *
 *    This file is part of MoSDi.
 *
 *    MoSDi is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    MoSDi is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoSDi.  If not, see <http://www.gnu.org/licenses/>.
 */

package mosdi.tests;

import java.util.Arrays;

import junit.framework.TestCase;
import mosdi.distributions.DistributionConvolver;
import mosdi.distributions.LazyDistributionConvolver;
import mosdi.util.Distributions;

public class DistributionConvolverTest extends TestCase {
	
	private static void assertEquals(double[] expected, double[] actual, double accuracy) {
		assertEquals(expected.length, actual.length);
		for (int i=0; i<expected.length; ++i) {
			assertTrue(Math.abs((expected[i]/actual[i])-1.0)<accuracy);
		}
	}

	public void testStaticConvolve() {
		double[] dist1 = {0.8, 0.2, Double.MIN_VALUE};
		double[] dist2 = {0.7, 0.3, 0.1, Double.MIN_VALUE};
		double[] conv = Distributions.convolve(dist1, dist2);
		double[] expectedResult = {0.8*0.7, 0.2*0.7+0.8*0.3, 0.2*0.3+0.8*0.1, 0.2*0.1};
		assertEquals(expectedResult, conv, 1e-10);
		conv = Distributions.convolveLengthPreserving(dist1, dist2, false);
		assertEquals(Arrays.copyOf(expectedResult,dist1.length), conv, 1e-10);
		conv = Distributions.convolveLengthPreserving(dist1, dist2, true);
		double[] expectedResult2 = {0.8*0.7, 0.2*0.7+0.8*0.3, 0.2*0.3+0.8*0.1+0.2*0.1};
		assertEquals(expectedResult2, conv, 1e-10);
	}
	
	public void testStaticConvolve2() {
		double[] dist1 = {0.8, 0.2, 0.1};
		double[] dist2 = {0.7, 0.3, 0.1, 0.5, 0.13, 0.17};
		double[] conv = Distributions.convolveLengthPreserving(dist1, dist2, true);
		double[] expectedResult = {0.8*0.7, 0.2*0.7+0.8*0.3, 0.1*0.7+(0.1+0.2)*0.3+(0.8+0.2+0.1)*(0.1+0.5+0.13+0.17)};
		assertEquals(expectedResult, conv, 1e-10);
	}

	public void testConvolve() {
		double[] dist = {0.6, 0.1, 0.3};
		DistributionConvolver dc = new LazyDistributionConvolver(dist);
		int n = 61;
		double[] expected = dist;
		for (int i=1; i<n; ++i) {
			expected = Distributions.convolve(expected, dist);
		}
		double[] actual = dc.getDistribution(n);
		assertEquals(expected, actual, 1e-10);
	}
	
}
